package com.lizhenhua.fmmall.service.serviceImpl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lizhenhua.fmmall.entity.IndexImg;
import com.lizhenhua.fmmall.mapper.IndexImgMapper;
import com.lizhenhua.fmmall.service.IndexImgService;
import com.lizhenhua.fmmall.vo.ResStatus;
import com.lizhenhua.fmmall.vo.ResultVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class IndexImgServiceImpl implements IndexImgService {
    @Autowired
    private IndexImgMapper indexImgMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public ResultVo listIndexImgs() {
        // string结构缓存轮播如信息
        List<IndexImg> indexImgs = null;
        try {
            String imgs = stringRedisTemplate.opsForValue().get("indexImgs");//他们是等价的 stringRedisTemplate.boundValueOps("indexImgs").get();
            // 1000个请求查到redis中的数据都是null
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (imgs != null) {
                //1. 把字符型转换为集合
                JavaType javaType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, IndexImg.class);
                indexImgs = objectMapper.readValue(imgs, javaType);
                return new ResultVo(ResStatus.OK, "success", indexImgs);
            } else {
                //2.  1000 个请求都会进入这里  service在spring容器中是单例的 1000个并发会启动1000个线程来访问 但是公用一个service实例
                //  synchronized (this) 让下面的事务串行起来
                synchronized (this) { // this 锁当前类的对象  先处理一个请求
                    // 再次查询redis 如果有直接返回
                    String s = stringRedisTemplate.opsForValue().get("indexImgs");

                    if (s == null) {
                        // 这1000个请求中，只有第一个在查redis为null  第二次查询我们已经设置过
                        // 给redis设置值
                        indexImgs = indexImgMapper.listIndexImg();// 查询数据库
                        if (indexImgs != null) {
                            String imgStr = objectMapper.writeValueAsString(indexImgs);
                            stringRedisTemplate.boundValueOps("indexImgs").set(imgStr);
                            // 设置过期时间为一天
                            stringRedisTemplate.boundValueOps("indexImgs").expire(1, TimeUnit.DAYS);
                        } else {
                            // 给他设置个空
//                            List<IndexImg> arr = new ArrayList<>();
//                            stringRedisTemplate.boundValueOps("indexImgs").set(objectMapper.writeValueAsString(arr));
                            stringRedisTemplate.boundValueOps("indexImgs").set("[]");
                            stringRedisTemplate.boundValueOps("indexImgs").expire(10, TimeUnit.SECONDS);
                        }

                    } else {

                        //1. 把字符型转换为集合
                        JavaType javaType = objectMapper.getTypeFactory().constructParametricType(ArrayList.class, IndexImg.class);
                        indexImgs = objectMapper.readValue(s, javaType);

                    }
                }
            }
            if (indexImgs.size() == 0) {
                return new ResultVo(ResStatus.NO, "fail", null);
            } else {
                return new ResultVo(ResStatus.OK, "success", indexImgs);
            }

        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return new ResultVo(ResStatus.OK, "转换异常", null);
        }

    }


}

